interface Observer {
  notify: ()=>void
}

class ConcreteObserver implements Observer {
  constructor (private name:string) {
  }

  notify () {
    console.log(`${this.name} has been notified`)
  }
}

class Subject {
  private observers: Observer[] = [];

  public addObserver (observer:Observer) {
    console.log(observer, 'is pushed')
    this.observers.push(observer)
  }

  public removeObserver (observer:Observer) {
    console.log('remove', observer)
    const index = this.observers.indexOf(observer)
    index !== -1 && this.observers.splice(index, 1)
  }

  public notifyObservers () {
    console.log('notify all observers:', this.observers)
    this.observers.forEach(observer => {
      observer.notify()
    })
  }
}

const subject = new Subject()
const ob1 = new ConcreteObserver('Sam')
const ob2 = new ConcreteObserver('None')

subject.addObserver(ob1)
subject.addObserver(ob2)

subject.notifyObservers()
